#ifndef BRAIN_H
#define BRAIN_H

/**
 * \file	brain.h
 * \brief	Declaration de la classe Brain representant un cerveau.
 */

#include "link.h"
#include "trackball.h"

/*! \def SULCIS
  Mode of picking : only picks up some sulcis of a brain.
 */
#define SULCIS 0

/*! \def GYRIS
  Mode of picking : only picks up some gyris of a brain.
 */
#define GYRIS 1

class Brain
{
	/*!
	 * \class Brain
	 * \brief Classe représentant un cerveau.
	 * 
	 * Classe représentant un cerveau par ses attributs d'interet.
	 *
	 */
	private :
		Mesh*			mesh;			/*! Pointer to a mesh representing the brain surface.*/
		Map*			map;			/*! Pointer to a map describing the feature value for each vertex.*/
		SegmentTree*	sulcis;			/*! Pointer to the root of a tree containing the sulcis of the brain.*/
		SegmentTree*	gyris;			/*! Pointer to the root of a tree containing the gyris of  the brain.*/
		vector<Link>	link;			/*! Array of link destined to contain the final matching between the source and the target.*/
		vector<int>		scores;			/*! Array of int containing, for each final link, the score attributed to the link. */

	public:
		/*!
		*  \brief Default constructor of the Brain class.
		*
		*  Default constructor of the Brain class : Every attributes are initialized to 0 (int,float,double,...) NULL (pointers) or are cleared (lists, stacks, ...).
		*/
	    Brain();
		
		/*!
		*  \brief Copy constructor of the Brain class.
		*
		*  Copy constructor of the Brain class.
		*/
		Brain( const Brain& _b );
		
		/*!
		*  \brief Destructor of the Brain class.
		*
		*  Destructor of the Brain class.
		*
		*  \warning THIS DESTRUCTOR DOESN'T DESTRUCT NEITHER THE MESH OF THE BRAIN NOR ITS MAP !
		*
		*/
		~Brain();
		
		/*!
		*  \brief Affectation operator of the Brain class.
		*
		*  Affectation operator of the Brain class.
		*/
		Brain& operator= ( const Brain& _b );
		
		/*!
		*  \brief Getter of the Brain class.
		*
		*  Getter of the Brain class.
		*
		*  \return (Mesh*) Returns the mesh representing the brain surface.
		*/
		Mesh* getMesh ();
		
		/*!
		*  \brief Getter of the Brain class.
		*
		*  Getter of the Brain class.
		*
		*  \return (Map*) Returns the map describing the mesh vertices feature values.
		*/
		Map* getMap ();
		
		/*!
		*  \brief Getter of the Brain class.
		*
		*  Getter of the Brain class.
		*
		*  \return (SegmentTree*) Returns the root of the tree containing the sulcis of th brain.
		*/
		SegmentTree* getSulcis ();
		
		/*!
		*  \brief Getter of the Brain class.
		*
		*  Getter of the Brain class.
		*
		*  \return (SegmentTree*) Returns the root of the tree containing the gyris of the brain.
		*/
		SegmentTree* getGyris ();
		
		/*!
		*  \brief Getter of the Brain class.
		*
		*  Getter of the Brain class.
		*
		*  \return (vector<Link>*) Returns the vector of links containing the final matching.
		*/
		vector<Link> getLink ();
		
		/*!
		*  \brief Getter of the Brain class.
		*
		*  Getter of the Brain class.
		*
		*  \return (vector<int>) Returns the vector of int containing the scores of all the final matchings.
		*/
		vector<int> getScores ();
		
		/*!
		*  \brief Getter of the Brain class.
		*
		*  Getter of the Brain class.
		*
		*  \return (int) Returns the score of the ith final link.
		*/
		int getIScore ( int _i );
		
		/*!
		*  \brief Setter of the Brain class.
		*
		*  Setter of the Brain class.
		*
		*  \param _mesh : Mesh to set as the representant of the brain.
		*
		*  \return (void)
		*/
		void setMesh ( Mesh* _mesh );
		
		/*!
		*  \brief Setter of the Brain class.
		*
		*  Setter of the Brain class.
		*
		*  \param _map : Map to set as the vertices feature values map.
		*
		*  \return (void)
		*/
		void setMap ( Map* _map );
		
		/*!
		*  \brief Setter of the Brain class.
		*
		*  Setter of the Brain class.
		*
		*  \param _sulcis : Tree containing the sulcis of the brain.
		*
		*  \return (void)
		*/
		void setSulcis ( SegmentTree* _sulcis );
		
		/*!
		*  \brief Setter of the Brain class.
		*
		*  Setter of the Brain class.
		*
		*  \param _gyris : Tree containing the gyris of the brain.
		*
		*  \return (void)
		*/
		void setGyris ( SegmentTree* _gyris );
		
		/*!
		*  \brief Setter of the Brain class.
		*
		*  Setter of the Brain class.
		*
		*  \param _v : Array of links describing the final matching.
		*
		*  \return (void)
		*/
		void setLink ( vector<Link> _v );
		
		/*!
		*  \brief Setter of the Brain class.
		*
		*  Setter of the Brain class.
		*
		*  \param _scores : Array of int containing each final matching score.
		*
		*  \return (void)
		*/
		void setScores ( vector<int> _scores );
		
		/*!
		*  \brief Setter of the Brain class.
		*
		*  Setter of the Brain class.
		*
		*  \param _i : Index of the link we want to set the score.
		*  \param _score : Score to attribute to the ith final link.
		*
		*  \return (void)
		*/
		void setIScore ( int _i, int _score );
		
		/*!
		*  \brief clears a brain.
		*
		*  clears a brain.
		*
		*  \return (void)
		*/
		void clear ();
		
		/*!
		*  \brief Saves a brain in the .brn format.
		*
		*  Saves a brain in the .brn format :
		*  Saves the mesh, and all the sulcis ancester in a file with their names and color.
		*  \ref explanationsaboutbrnformat "See the .brn format description"
		*
		*  \param _path : Path to save the brain.
		*
		*  \return (int) Returns -1 if a problem occured during saving, 1 else.
		*/
		int save ( char* _path );
		
		/*!
		*  \brief Loads a brain in the .brn format.
		*
		*  Loads a brain in the .brn format :
		*  Loads the mesh, and all the sulcis of a brain with their names and color.
		*  \ref explanationsaboutbrnformat "See the .brn format description"
		*
		*  \param _path : Brain to load.
		*
		*  \return (int) Returns -1 if a problem occured during loading, 1 else.
		*/
		int load ( char* _path );
		
		/*!
		*  \brief Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*
		*  Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*  according to an intersection criteria.
		*
		*  \param _b : Target brain to match the brain calling this method.
		*
		*  \return (vector<Link>) Array of Link (1 per ancester segment in the source tree) representing the matching between the source and target segments.
		*/
		vector<Link> linkBy_Intersection ( Brain _b );
		
		/*!
		*  \brief Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*
		*  Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*  according to a distance criteria.
		*  The distance choosen here is simply the number of edge separating two vertices in the mesh.
		*
		*  \param _b : Target brain to match the brain calling this method.
		*  \param _distMax : Distance maximum to considerate two segments as neighbours.
		*
		*  \return (vector<Link>) Array of Link (1 per ancester segment in the source tree) representing the matching between the source and target segments.
		*/
		vector<Link> linkBy_Distance ( Brain _b, int _distMax );
		
		/*!
		*  \brief Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*
		*  Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*  according to a depth similarity criteria.
		*
		*  \param _b : Target brain to match the brain calling this method.
		*  \param _distMax : Distance maximum to considerate two segments as neighbours. The default is set to 0. That means we match two sulcis only if they have the same depth (knowing that the map has been segented).
		*
		*  \return (vector<Link>) Array of Link (1 per ancester segment in the source tree) representing the matching between the source and target segments.
		*/
		vector<Link> linkBy_Depth ( Brain _b, int _distMax = 0 );
		
		/*!
		*  \brief Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*
		*  Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*  according to an area similarity criteria.
		*
		*  \param _b : Target brain to match the brain calling this method.
		*  \param _distMax : Distance maximum to considerate two segments as neighbours. The default is set to 0. That means we match two sulcis only if they have the same depth (knowing that the map has been segented).
		*
		*  \return (vector<Link>) Array of Link (1 per ancester segment in the source tree) representing the matching between the source and target segments.
		*/
		vector<Link> linkBy_Area ( Brain _b, double _distMax );
		
		/*!
		*  \brief Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*
		*  Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*  according to a similarity of the Bot point of the bounding box of the nodes.
		*
		*  Please see the SegmentTreeList::getMatchBy_BoundingBoxBotX method.
		*
		*  \param _b : Target brain to match the brain calling this method.
		*  \param _distMax : Distance maximum to considerate two segments as neighbours.
		*
		*  \return (vector<Link>) Array of Link (1 per ancester segment in the source tree) representing the matching between the source and target segments.
		*/
		vector<Link> linkBy_BBoxBotX ( Brain _b, int _distMax );
		
		/*!
		*  \brief Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*
		*  Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*  according to a similarity of the Bot point of the bounding box of the nodes.
		*
		*  Please see the SegmentTreeList::getMatchBy_BoundingBoxTopX method.
		*
		*  \param _b : Target brain to match the brain calling this method.
		*  \param _distMax : Distance maximum to considerate two segments as neighbours.
		*
		*  \return (vector<Link>) Array of Link (1 per ancester segment in the source tree) representing the matching between the source and target segments.
		*/
		vector<Link> linkBy_BBoxTopX ( Brain _b, int _distMax );
		
		/*!
		*  \brief See the linkBy_BBoxBotX description.
		*/
		vector<Link> linkBy_BBoxBotY ( Brain _b, int _distMax );
		
		/*!
		*  \brief See the linkBy_BBoxTopX description.
		*/
		vector<Link> linkBy_BBoxTopY ( Brain _b, int _distMax );
		
		/*!
		*  \brief See the linkBy_BBoxBotX description.
		*/
		vector<Link> linkBy_BBoxBotZ ( Brain _b, int _distMax );
		
		/*!
		*  \brief See the linkBy_BBoxTopX description.
		*/
		vector<Link> linkBy_BBoxTopZ ( Brain _b, int _distMax );
		
		/*!
		*  \brief Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*
		*  Creates an array of links representing the matching of the revelant elements (ancester nodes in the trees of a brain) of the brain calling the method onto the target brain.
		*  according to a similarity of the Bot point of the bounding box of the nodes.
		*
		*  Please see the SegmentTreeList::getMatchBy_BoundingBoxX method.
		*
		*  \param _b : Target brain to match the brain calling this method.
		*  \param _distMax : Distance maximum to considerate two segments as neighbours.
		*
		*  \return (vector<Link>) Array of Link (1 per ancester segment in the source tree) representing the matching between the source and target segments.
		*/
		vector<Link> linkBy_BBoxX ( Brain _b, int _distMax );
		
		/*!
		*  \brief See the linkBy_BBoxX description.
		*/
		vector<Link> linkBy_BBoxY ( Brain _b, int _distMax );
		
		/*!
		*  \brief See the linkBy_BBoxX description.
		*/
		vector<Link> linkBy_BBoxZ ( Brain _b, int _distMax );
		
		/*!
		*  \brief Mixes one or several arrays of link to create the final matching from those.
		*
		*  Mixes one or several arrays of link to create the final matching from those :
		*  You should mix several arrays previously computed with different criterias (distance, area, ... ).
		*
		*  Each array is given a weight, so, we can compute for each , match of each node of the brain's tree a score.
		*  We then see if the match with the highest score has a score higher than the threshold. 
		*  If it is the case, the match is marked as final matching and the link array of the brain is filled.
		*
		*  This is a function you can give as many parameters you want. BUT ! Be carefull : you must follow the following convention :
		*  Three parameters minimum should be given : One threshold, one pointer to an array of link previously computed and one weight for this array.
		*  Parameters are then allways paired : one pointer to a link array THEN one weight.
		*  Don't forget to give a NULL parameter at the end of yours to let the method know that it was the last parameter.
		*  
		*  Example :
		*  \include ExampleLinkByCriteriaDescription.dox
		*
		*  \param _thresh : Threshold for the score. For each node of the brain tree, if a score is higher than the threshold, it is potentially one of the final match.
		*  \param _v : Pointer on an array of link previously computed according to a specific criteria : area, distance...
		*  \param _weigth : Weight of the _v array for calculating the different scores.
		*  \param ... : Then list as many COUPLES of array-weight. Dont forget to give a NULL parameter at the end of this list.
		*
		*  \return (void)
		*/
		void linkBy_Crtiteria ( int _thresh, vector<Link>* _v, int _weight, ... );
		
		/*!
		*  \brief Tries to improve the final link array.
		*
		*  Tries to improve the final link array :
		*  Look if the reference node has a better match in the target node's sons, and change or not consequently the match.
		*
		*  \return (void)
		*/
		void improveLinks( Brain _target );
		
		/*!
		*  \brief Automatically set a different color for each elements on the brain.
		*
		*  Automatically set a different color for each elements on the brain.
		*  These elements are the ones that are the root tree and the root itself of the brain.
		*
		*  \return (void)
		*/
		void colorElements ( float _r = -1, float _g = 0, float _b = 0 );
		
		void regroupSulcis ( int _distMax );
		
		/*!
		*  \brief OpenGL routine to display a brain's mesh.
		*
		*  OpenGL routine to display a brain's mesh in different ways.
		*  The color displayed will be the color given in parameter via the three arguments (r,b,b).
		*
		*  \param _mode : mode we want to display the mesh. Can be VERTICES, EDGES, FACES or SMOOTH.
		*  \param _r : red component of the color to display.
		*  \param _g : green component of the color to display.
		*  \param _b : blue component of the color to display.
		*
		*  \return (void)
		*/
		void displaySurface ( int _mode, float _r = 1, float _g = 1, float _b  = 1);
		
		/*!
		*  \brief OpenGL routine to display sulcis of a brain (only tree ancesters).
		*
		*  OpenGL routine to display sulcis of a brain (only tree ancesters).
		*  The color displayed will be the color given in parameter via the three arguments (r,b,b).
		*
		*  \param _mode : mode we want to display the mesh. Can be OWN_COLOR, OTHER_COLOR or MESH_COLOR
		*  \param _r : red component of the color to display. Only useful if mode is OTHER_COLOR.
		*  \param _g : green component of the color to display. Only useful if mode is OTHER_COLOR.
		*  \param _b : blue component of the color to display. Only useful if mode is OTHER_COLOR.
		*
		*  \return (void)
		*/
		void displaySulcis ( int _mode, float _r = 1, float _g = 0 , float _b = 0 );
		
		/*!
		*  \brief Displays a landmark in the 3D scene.
		*
		*  Displays a landmark in the 3D scene : the red axe is the Ox axe, the green one is the Oy and the bleu one is the Oz.
		*  
		*  \param _x : abscissa of the origin to dislay the landmark. Default value is 0.
		*  \param _y : ordinate of the origin to dislay the landmark. Default value is 0.
		*  \param _z : height of the origin to dislay the landmark. Default value is 0.
		*  
		*  \return (void)
		*/
		static void displayLandMark ( double _x = 0, double _y = 0, double _z = 0, int _size = 1 );
		
		/*!
		*  \brief Displays the revelent sulcis of the brain in color.
		*
		*  Displays the revelent sulcis of the brain in color :
		*  By default, each sulcus will be displayed in the same color than the target sulcus they match in the target brain. If no match has been found for one sulcus, it will be displayed in black.
		*  
		*  \param _mode : mode we want to display the mesh. Can be OWN_COLOR, OTHER_COLOR or MESH_COLOR. Can also be PICKING in a special way.
		*  \param _r : red component of the color to display. Only useful if mode is OTHER_COLOR.
		*  \param _g : green component of the color to display. Only useful if mode is OTHER_COLOR.
		*  \param _b : blue component of the color to display. Only useful if mode is OTHER_COLOR.
		*
		*  Use example :
		*  \code
		*	void dispayWindowSource ()
		*	{
		*		...
		*		source.displaySurface( FACE, 1,1,1 );		//Displays the source mesh in FACE mode and in white color.
		*		source.displayLinkReferences();				//Displays the revelant sulcis colored.
		*		...
		*	}
		*
		*	void dispayWindowTarget ()
		*	{
		*		...
		*		target.displaySurface( FACE, 1,1,1 );		//Displays the target mesh in FACE mode and in white color.
		*		source.displayLinkReferences();				//Displays the target suclis matched by the source ones. So we display it over the target mesh.
		*		...
		*	}
		*  \endcode
		*
		*  \sa displayLinkMatched
		*  
		*  \return (void)
		*/
		void displayLinkReferences ( int _mode = OWN_COLOR, float _r = 1, float _g = 1, float _b  = 1);
		
		/*!
		*  \brief Displays the target sulcis matched by the source ones in color.
		*
		*  Displays the target sulcis matched by the source ones in color.
		*  Each target sulcus was previously given a single color via the colorElement method. By default this color will be displayed.
		*  
		*  \param _mode : mode we want to display the mesh. Can be OWN_COLOR, OTHER_COLOR or MESH_COLOR.
		*  \param _r : red component of the color to display. Only useful if mode is OTHER_COLOR.
		*  \param _g : green component of the color to display. Only useful if mode is OTHER_COLOR.
		*  \param _b : blue component of the color to display. Only useful if mode is OTHER_COLOR.
		*
		*  Use example :
		*  \code
		*	void dispayWindowSource ()
		*	{
		*		...
		*		source.displaySurface( FACE, 1,1,1 );		//Displays the source mesh in FACE mode and in white color.
		*		source.displayLinkReferences();				//Displays the revelant sulcis colored.
		*		...
		*	}
		*
		*	void dispayWindowTarget ()
		*	{
		*		...
		*		target.displaySurface( FACE, 1,1,1 );		//Displays the target mesh in FACE mode and in white color.
		*		source.displayLinkReferences();				//Displays the target suclis matched by the source ones. So we display it over the target mesh.
		*		...
		*	}
		*  \endcode
		*
		*  \sa displayLinkReferences
		*  
		*  \return (void)
		*/
		void displayLinkMatched ( int _mode = OWN_COLOR, float _r = 1, float _g = 1, float _b  = 1);
		
		/*!
		*  \brief OpenGL picking method to pick a node (an ancester) of a brain element tree.
		*
		*  OpenGL picking method to pick a node (an ancester) of a segment tree.
		*
		*  \param _x : Position of the mouse in the window along the Ox axe.
		*  \param _y : Position of the mouse in the window along the Oy axe.
		*  \param _mode : Picking mode, selects what the user wants to pick. Can be SULCIS or GYRIS.
		*  \param _t : trackball used in the rendering mode. Only if a trackball is used, otherwise this parameter is NULL by default.
		*
		*  \return (SegmentTree*) Returns the node picked by the user.
		*/
		SegmentTree* pickingNode ( int _x, int _y, int _mode = SULCIS, TrackBall* _t = NULL );
		
		/*!
		*  \brief OpenGL picking method to pick a node from the link array (an ancester) of a brain.
		*
		*  OpenGL picking method to pick a node from the link array (an ancester) of a brain.
		*
		*  \param _x : Position of the mouse in the window along the Ox axe.
		*  \param _y : Position of the mouse in the window along the Oy axe.
		*  \param _t : trackball used in the rendering mode. Only if a trackball is used, otherwise this parameter is NULL by default.
		*
		*  \return (SegmentTree*) Returns the node picked by the user.
		*/
		SegmentTree* pickingLinkReference ( int _x, int _y, TrackBall* _t = NULL );
};

#endif // BRAIN_H
